<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>co_composed</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../boost_asio.html" title="Boost.Asio">
<link rel="up" href="../reference.html" title="Reference">
<link rel="prev" href="cancellation_type_t.html" title="cancellation_type_t">
<link rel="next" href="co_spawn.html" title="co_spawn">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="cancellation_type_t.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="co_spawn.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_asio.reference.co_composed"></a><a class="link" href="co_composed.html" title="co_composed">co_composed</a>
</h3></div></div></div>
<p>
        <a class="indexterm" name="boost_asio.indexterm.co_composed"></a>
      </p>
<p>
        Creates an initiation function object that may be used to launch a coroutine-based
        composed asynchronous operation.
      </p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span>
    <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">Signatures</span><span class="special">,</span>
    <span class="keyword">typename</span> <span class="identifier">Implementation</span><span class="special">,</span>
    <span class="keyword">typename</span><span class="special">...</span> <span class="identifier">IoObjectsOrExecutors</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">co_composed</span><span class="special">(</span>
    <span class="identifier">Implementation</span> <span class="special">&amp;&amp;</span> <span class="identifier">implementation</span><span class="special">,</span>
    <span class="identifier">IoObjectsOrExecutors</span> <span class="special">&amp;&amp;...</span> <span class="identifier">io_objects_or_executors</span><span class="special">);</span>
</pre>
<p>
        The co_composed utility simplifies the implementation of composed asynchronous
        operations by automatically adapting a coroutine to be an initiation function
        object for use with <code class="computeroutput"><span class="identifier">async_initiate</span></code>.
        When awaiting asynchronous operations, the coroutine automatically uses a
        conforming intermediate completion handler.
      </p>
<h5>
<a name="boost_asio.reference.co_composed.h0"></a>
        <span class="phrase"><a name="boost_asio.reference.co_composed.parameters"></a></span><a class="link" href="co_composed.html#boost_asio.reference.co_composed.parameters">Parameters</a>
      </h5>
<div class="variablelist">
<p class="title"><b></b></p>
<dl class="variablelist">
<dt><span class="term">implementation</span></dt>
<dd><p>
              A function object that contains the coroutine-based implementation
              of the composed asynchronous operation. The first argument to the function
              object represents the state of the operation, and may be used to test
              for cancellation. The remaining arguments are those passed to <code class="computeroutput"><span class="identifier">async_initiate</span></code> after the completion
              token.
            </p></dd>
<dt><span class="term">io_objects_or_executors</span></dt>
<dd><p>
              Zero or more I/O objects or I/O executors for which outstanding work
              must be maintained while the operation is incomplete.
            </p></dd>
</dl>
</div>
<h5>
<a name="boost_asio.reference.co_composed.h1"></a>
        <span class="phrase"><a name="boost_asio.reference.co_composed.per_operation_cancellation"></a></span><a class="link" href="co_composed.html#boost_asio.reference.co_composed.per_operation_cancellation">Per-Operation
        Cancellation</a>
      </h5>
<p>
        By default, terminal per-operation cancellation is enabled for composed operations
        that use co_composed. To disable cancellation for the composed operation,
        or to alter its supported cancellation types, call the state's <code class="computeroutput"><span class="identifier">reset_cancellation_state</span></code> function.
      </p>
<h5>
<a name="boost_asio.reference.co_composed.h2"></a>
        <span class="phrase"><a name="boost_asio.reference.co_composed.examples"></a></span><a class="link" href="co_composed.html#boost_asio.reference.co_composed.examples">Examples</a>
      </h5>
<p>
        The following example illustrates manual error handling and explicit checks
        for cancellation. The completion handler is invoked via a <code class="computeroutput"><span class="identifier">co_yield</span></code>
        to the state's <code class="computeroutput"><span class="identifier">complete</span></code> function,
        which never returns.
      </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CompletionToken</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">async_echo</span><span class="special">(</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">&amp;</span> <span class="identifier">socket</span><span class="special">,</span>
    <span class="identifier">CompletionToken</span><span class="special">&amp;&amp;</span> <span class="identifier">token</span><span class="special">)</span>
<span class="special">{</span>
  <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_initiate</span><span class="special">&lt;</span>
    <span class="identifier">CompletionToken</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)&gt;(</span>
      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">co_composed</span><span class="special">(</span>
        <span class="special">[](</span><span class="keyword">auto</span> <span class="identifier">state</span><span class="special">,</span> <span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">&amp;</span> <span class="identifier">socket</span><span class="special">)</span> <span class="special">-&gt;</span> <span class="keyword">void</span>
        <span class="special">{</span>
          <span class="identifier">state</span><span class="special">.</span><span class="identifier">reset_cancellation_state</span><span class="special">(</span>
            <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">enable_terminal_cancellation</span><span class="special">());</span>

          <span class="keyword">while</span> <span class="special">(!</span><span class="identifier">state</span><span class="special">.</span><span class="identifier">cancelled</span><span class="special">())</span>
          <span class="special">{</span>
            <span class="keyword">char</span> <span class="identifier">data</span><span class="special">[</span><span class="number">1024</span><span class="special">];</span>
            <span class="keyword">auto</span> <span class="special">[</span><span class="identifier">e1</span><span class="special">,</span> <span class="identifier">n1</span><span class="special">]</span> <span class="special">=</span>
              <span class="identifier">co_await</span> <span class="identifier">socket</span><span class="special">.</span><span class="identifier">async_read_some</span><span class="special">(</span>
                <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">data</span><span class="special">));</span>

            <span class="keyword">if</span> <span class="special">(</span><span class="identifier">e1</span><span class="special">)</span>
              <span class="identifier">co_yield</span> <span class="identifier">state</span><span class="special">.</span><span class="identifier">complete</span><span class="special">(</span><span class="identifier">e1</span><span class="special">);</span>

            <span class="keyword">if</span> <span class="special">(!!</span><span class="identifier">state</span><span class="special">.</span><span class="identifier">cancelled</span><span class="special">())</span>
              <span class="identifier">co_yield</span> <span class="identifier">state</span><span class="special">.</span><span class="identifier">complete</span><span class="special">(</span>
                <span class="identifier">make_error_code</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">error</span><span class="special">::</span><span class="identifier">operation_aborted</span><span class="special">));</span>

            <span class="keyword">auto</span> <span class="special">[</span><span class="identifier">e2</span><span class="special">,</span> <span class="identifier">n2</span><span class="special">]</span> <span class="special">=</span>
              <span class="identifier">co_await</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">socket</span><span class="special">,</span>
                <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">n1</span><span class="special">));</span>

            <span class="keyword">if</span> <span class="special">(</span><span class="identifier">e2</span><span class="special">)</span>
              <span class="identifier">co_yield</span> <span class="identifier">state</span><span class="special">.</span><span class="identifier">complete</span><span class="special">(</span><span class="identifier">e2</span><span class="special">);</span>
          <span class="special">}</span>
        <span class="special">},</span> <span class="identifier">socket</span><span class="special">),</span>
      <span class="identifier">token</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">socket</span><span class="special">));</span>
<span class="special">}</span>
</pre>
<p>
        This next example shows exception-based error handling and implicit checks
        for cancellation. The completion handler is invoked after returning from
        the coroutine via <code class="computeroutput"><span class="identifier">co_return</span></code>.
        Valid <code class="computeroutput"><span class="identifier">co_return</span></code> values are
        specified using completion signatures passed to the <code class="computeroutput"><span class="identifier">co_composed</span></code>
        function.
      </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CompletionToken</span><span class="special">&gt;</span>
<span class="keyword">auto</span> <span class="identifier">async_echo</span><span class="special">(</span><span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">&amp;</span> <span class="identifier">socket</span><span class="special">,</span>
    <span class="identifier">CompletionToken</span><span class="special">&amp;&amp;</span> <span class="identifier">token</span><span class="special">)</span>
<span class="special">{</span>
  <span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_initiate</span><span class="special">&lt;</span>
    <span class="identifier">CompletionToken</span><span class="special">,</span> <span class="keyword">void</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)&gt;(</span>
      <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">co_composed</span><span class="special">&lt;</span>
        <span class="keyword">void</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">error_code</span><span class="special">)&gt;(</span>
          <span class="special">[](</span><span class="keyword">auto</span> <span class="identifier">state</span><span class="special">,</span> <span class="identifier">tcp</span><span class="special">::</span><span class="identifier">socket</span><span class="special">&amp;</span> <span class="identifier">socket</span><span class="special">)</span> <span class="special">-&gt;</span> <span class="keyword">void</span>
          <span class="special">{</span>
            <span class="keyword">try</span>
            <span class="special">{</span>
              <span class="identifier">state</span><span class="special">.</span><span class="identifier">throw_if_cancelled</span><span class="special">(</span><span class="keyword">true</span><span class="special">);</span>
              <span class="identifier">state</span><span class="special">.</span><span class="identifier">reset_cancellation_state</span><span class="special">(</span>
                <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">enable_terminal_cancellation</span><span class="special">());</span>

              <span class="keyword">for</span> <span class="special">(;;)</span>
              <span class="special">{</span>
                <span class="keyword">char</span> <span class="identifier">data</span><span class="special">[</span><span class="number">1024</span><span class="special">];</span>
                <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span> <span class="special">=</span> <span class="identifier">co_await</span> <span class="identifier">socket</span><span class="special">.</span><span class="identifier">async_read_some</span><span class="special">(</span>
                    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">data</span><span class="special">));</span>

                <span class="identifier">co_await</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">async_write</span><span class="special">(</span><span class="identifier">socket</span><span class="special">,</span>
                    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">asio</span><span class="special">::</span><span class="identifier">buffer</span><span class="special">(</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">n</span><span class="special">));</span>
              <span class="special">}</span>
            <span class="special">}</span>
            <span class="keyword">catch</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">system</span><span class="special">::</span><span class="identifier">system_error</span><span class="special">&amp;</span> <span class="identifier">e</span><span class="special">)</span>
            <span class="special">{</span>
              <span class="identifier">co_return</span> <span class="special">{</span><span class="identifier">e</span><span class="special">.</span><span class="identifier">code</span><span class="special">()};</span>
            <span class="special">}</span>
          <span class="special">},</span> <span class="identifier">socket</span><span class="special">),</span>
      <span class="identifier">token</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">socket</span><span class="special">));</span>
<span class="special">}</span>
</pre>
<h5>
<a name="boost_asio.reference.co_composed.h3"></a>
        <span class="phrase"><a name="boost_asio.reference.co_composed.requirements"></a></span><a class="link" href="co_composed.html#boost_asio.reference.co_composed.requirements">Requirements</a>
      </h5>
<p>
        <span class="emphasis"><em>Header: </em></span><code class="literal">boost/asio/co_composed.hpp</code>
      </p>
<p>
        <span class="emphasis"><em>Convenience header: </em></span><code class="literal">boost/asio.hpp</code>
      </p>
</div>
<div class="copyright-footer">Copyright © 2003-2025 Christopher M.
      Kohlhoff<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="cancellation_type_t.html"><img src="../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../reference.html"><img src="../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../boost_asio.html"><img src="../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="co_spawn.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
